import os
import re


class Record:
    def __init__(self, data, isJson = False) :
        if (isJson) :
            self.jsonData = data
            self.rawData = ""
            self._fromJson()
        else :
            self.rawData = data
            self.jsonData = {"fields" : {}}
            self._toJson()

    def _toJson(self) :
        pattern = re.compile(r'\w+, [^\)]*', re.I)
        matchs = pattern.findall(self.rawData)
        recordType = matchs[0].split(',')

        self.jsonData["type"] = recordType[0]
        self.jsonData["PVName"] = recordType[1].strip().replace('"','')

        for index in range(1, len(matchs)):
            fieldType = matchs[index].split(',')
            self.jsonData["fields"][fieldType[0]] = fieldType[1].strip().replace('"','')


    def _fromJson(self) :
        self.rawData = 'record({}, "{}")\n{{\n'.format(self.jsonData["type"], self.jsonData["PVName"])
        for key, value in  self.jsonData["fields"].items() :
            self.rawData += '    field({}, "{}")\n'.format(key, value)
        self.rawData += "}\n\n"


class RecordFile:
    def __init__(self) :
        self.records = []

    def readFromLocalFile(self, fileName):
        if not os.path.exists(fileName) :
            return

        self.fileName = fileName
        f = open(self.fileName, "r")
        self.rawData = f.read()
        f.close()

        self.records = []
        pattern = re.compile(r'record\([^\}]*\}', re.I)
        recordTexts = pattern.findall(self.rawData)
        for recordText in recordTexts:
            self.records.append(Record(recordText))

        self.jsonData = {
            "version" : 1,
            "records" : []
        }
        self.jsonData["fileName"] = self.fileName
        recordList = []

        for record in self.records :
            recordList.append(record.jsonData)

        self.jsonData["records"] = recordList

    def writeToLocalFile(self, fileName) :
        self.fileName = fileName
        f = open(self.fileName, "w")
        f.write(self.rawData)
        f.close()

    def updateByJson(self, jsonData) :
        self.jsonData = jsonData
        self.rawData = ""
        self.records = []
        for jsonRecord in jsonData["records"] :
            self.records.append(Record(jsonRecord, True))

        for record in self.records :
            self.rawData += record.rawData

    def getJson(self) :
        return self.jsonData

    def getRaw(self) :
        return self.rawData


class recordsManage:
    def __init__(self) :
        self.recordsFile = {}

    def addrecordByfile(self, recordFileName) :
        file = RecordFile()
        file.readFromLocalFile(recordFileName)
        self.recordsFile[recordFileName] = file
        self.recordsFile[recordFileName].getJson()

    def addrecordByJson(self, jsonData) :
        if not ("fileName" in jsonData) :
            return

        if not (jsonData["fileName"] in self.recordsFile) :
            self.recordsFile[jsonData["fileName"]] = RecordFile()

        self.recordsFile[jsonData["fileName"]].updateByJson(jsonData)
        self.recordsFile[jsonData["fileName"]].writeToLocalFile(jsonData["fileName"])
        self.recordsFile[jsonData["fileName"]].getRaw()



# testFile = {'version': 1, 'records': [{'fields': {'SCAN': ' "Passive"', 'DTYP': ' "s7nodave"', 'OUT': ' "@NBIPLC DB1:DBX0.7"'}, 'type': 'ao', 'PVName': ' "PISpectrometer:motorOffOut"'}, {'fields': {'SCAN': ' ".1 second"', 'DTYP': ' "s7nodave"', 'INP': ' "@NBIPLC DB1:DBX0.7"'}, 'type': 'ai', 'PVName': ' "PISpectrometer:motorOffIn"'}, {'fields': {'SCAN': ' "Passive"', 'DTYP': ' "s7nodave"', 'OUT': ' "@NBIPLC DB1:DBX1.0"'}, 'type': 'ao', 'PVName': ' "PISpectrometer:motorOnOut"'}, {'fields': {'SCAN': ' ".1 second"', 'DTYP': ' "s7nodave"', 'INP': ' "@NBIPLC DB1:DBX1.0"'}, 'type': 'ai', 'PVName': ' "PISpectrometer:motorOnIn"'}], 'fileName': './Test.db'}

RM = recordsManage()


def db_read(file_path:str) -> dict:
    RM.addrecordByfile(file_path)
    data = RM.recordsFile[file_path].getJson()
    return data


def db_wirte(data:dict) -> bool:
    RM.addrecordByJson(data)
    return True


